package com.xiaomi.service.impl;

import com.xiaomi.exception.BusinessException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xiaomi.dto.SignalDTO;
import com.xiaomi.entity.Rule;
import com.xiaomi.entity.Signal;
import com.xiaomi.entity.Vehicle;
import com.xiaomi.mapper.SignalMapper;
import com.xiaomi.mapper.VehicleMapper;
import com.xiaomi.service.RuleService;
import com.xiaomi.service.SignalService;
import com.xiaomi.vo.SignalVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class SignalServiceImpl implements SignalService {
    @Autowired
    private SignalMapper signalMapper;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Autowired
    private RuleService ruleService;
    @Autowired
    private VehicleMapper vehicleMapper;

    private static final String SIGNAL_CACHE_PREFIX = "signal:car:";
    private static final long SIGNAL_CACHE_EXPIRE_TIME = 5 * 60; // 5分钟

    /**
     * 将signal转变为VO
     * @param signal
     * @return
     */
    private SignalVO convertToSignalVO(Signal signal) {
        SignalVO signalVO = new SignalVO();
        BeanUtils.copyProperties(signal, signalVO);
        signalVO.setCurrentNow(signal.getCurrent());
        signalVO.setVoltageNow(signal.getVoltage());
        return signalVO;
    }
    /**
     * 上传信息
     * @param signalDTO
     */
    @Transactional
    @Override
    public void add(SignalDTO signalDTO) {
        Signal signal = new Signal();
        BeanUtils.copyProperties(signalDTO, signal);
        signal.setSignalTime(LocalDateTime.now());

        // Redis key格式：carId_voltage/current
        String maxVoltageKey = "car:" + signal.getVehicleFrameNumber() + ":max_voltage";
        String minVoltageKey = "car:" + signal.getVehicleFrameNumber() + ":min_voltage";
        String maxCurrentKey = "car:" + signal.getVehicleFrameNumber() + ":max_current";
        String minCurrentKey = "car:" + signal.getVehicleFrameNumber() + ":min_current";

        // 获取当前电压和电流
        Double voltage = signal.getVoltage();
        Double current = signal.getCurrent();

        // 检查Redis中是否存在最大最小电压电流数据
        Double maxVoltage = (Double) redisTemplate.opsForValue().get(maxVoltageKey);
        Double minVoltage = (Double) redisTemplate.opsForValue().get(minVoltageKey);
        Double maxCurrent = (Double) redisTemplate.opsForValue().get(maxCurrentKey);
        Double minCurrent = (Double) redisTemplate.opsForValue().get(minCurrentKey);

        // 如果Redis中不存在最大最小电压电流数据，则将当前电压电流作为初始值
        if (maxVoltage == null || minVoltage == null || maxCurrent == null || minCurrent == null) {
            redisTemplate.opsForValue().set(maxVoltageKey, voltage);
            redisTemplate.opsForValue().set(minVoltageKey, voltage);
            redisTemplate.opsForValue().set(maxCurrentKey, current);
            redisTemplate.opsForValue().set(minCurrentKey, current);
        } else {
            // 如果Redis中存在最大最小电压电流数据，则比较当前电压电流和Redis中的最大最小电压电流的值
            if (voltage > maxVoltage) {
                redisTemplate.opsForValue().set(maxVoltageKey, voltage);
            }
            if (voltage < minVoltage) {
                redisTemplate.opsForValue().set(minVoltageKey, voltage);
            }
            if (current > maxCurrent) {
                redisTemplate.opsForValue().set(maxCurrentKey, current);
            }
            if (current < minCurrent)
                redisTemplate.opsForValue().set(minCurrentKey, current);
        }

        signal.setStatus(0);
        signalMapper.insert(signal);


        // 将新增的信号写入Redis缓存，设置5分钟过期时间
        String signalCacheKey = SIGNAL_CACHE_PREFIX + signal.getVehicleFrameNumber();
        SignalVO signalVO = convertToSignalVO(signal);
        signalVO.setVoltageMax(maxVoltage);
        signalVO.setVoltageMin(minVoltage);
        signalVO.setCurrentMax(maxCurrent);
        signalVO.setCurrentMin(minCurrent);

        redisTemplate.opsForValue().set(signalCacheKey, signalVO, SIGNAL_CACHE_EXPIRE_TIME, TimeUnit.SECONDS);
    }

    /**
     * 从redis中获取信息
     * @param carFrameNumber
     * @return
     */
    private SignalVO getCachedSignalVOByCarId(Long carFrameNumber) {
        String signalCacheKey = SIGNAL_CACHE_PREFIX + carFrameNumber;
        return (SignalVO) redisTemplate.opsForValue().get(signalCacheKey);
    }
    private Long getCarIdFromSignalId(Integer signalId) {
        return signalMapper.selectById(signalId).getVehicleFrameNumber();
    }
    /**
     * 查询信息并且查询当前车辆的最大最小电压电流
     * @param id
     * @return
     */
    @Override
    public SignalVO getSignalById(Integer id) {
        // 先尝试从Redis缓存中获取
        SignalVO cachedSignalVO = getCachedSignalVOByCarId(getCarIdFromSignalId(id));
        if (cachedSignalVO != null) {
            return cachedSignalVO;
        }

        Signal signal = signalMapper.selectById(id);
        SignalVO signalVO = new SignalVO();
        BeanUtils.copyProperties(signal, signalVO);
        signalVO.setCurrentNow(signal.getCurrent());
        signalVO.setVoltageNow(signal.getVoltage());

        // Redis key格式：carId_voltage/current
        String maxVoltageKey = "car:" + signal.getVehicleFrameNumber() + ":max_voltage";
        String minVoltageKey = "car:" + signal.getVehicleFrameNumber() + ":min_voltage";
        String maxCurrentKey = "car:" + signal.getVehicleFrameNumber() + ":max_current";
        String minCurrentKey = "car:" + signal.getVehicleFrameNumber() + ":min_current";

        // 获取当前电压和电流
        Double maxVoltage = (Double) redisTemplate.opsForValue().get(maxVoltageKey);
        Double minVoltage = (Double) redisTemplate.opsForValue().get(minVoltageKey);
        Double maxCurrent = (Double) redisTemplate.opsForValue().get(maxCurrentKey);
        Double minCurrent = (Double) redisTemplate.opsForValue().get(minCurrentKey);
        signalVO.setVoltageMax(maxVoltage);
        signalVO.setVoltageMin(minVoltage);
        signalVO.setCurrentMax(maxCurrent);
        signalVO.setCurrentMin(minCurrent);

        // 将查询结果存入Redis缓存
        String signalCacheKey = SIGNAL_CACHE_PREFIX + signal.getVehicleFrameNumber();
        redisTemplate.opsForValue().set(signalCacheKey, signalVO, SIGNAL_CACHE_EXPIRE_TIME, TimeUnit.SECONDS);

        return signalVO;
    }

    /**
     * 查询未处理信号 -> status=0
     * @return
     */
    @Override
    public List<Signal> getUnprocessedSignals() {
        return signalMapper.selectUnprocessedSignals();
    }

    /**
     * 处理完的信号变状态
     * @param signalId
     */
    @Override
    public void updateSignalStatus(Integer signalId) {
        Signal signal = Signal.builder()
                .signalId(signalId)
                .status(1)
                .build();
        signalMapper.updateStatus(signal);
    }

    @Override
    public SignalVO getSignalsByCarFrameNumber(Long carFrameNumber) {
        // 先尝试从Redis缓存中获取
        SignalVO cachedSignalVO = getCachedSignalVOByCarId(carFrameNumber);
        if (cachedSignalVO != null) {
            return cachedSignalVO;
        }

        // 如果Redis中没有，则从数据库中获取
        List<Signal> signals = signalMapper.selectByCarFrameNumber(carFrameNumber);
        if (signals.isEmpty()) {
            return null;
        }

        // 假设我们只需要最新的信号信息
        Signal latestSignal = signals.get(signals.size() - 1);
        SignalVO signalVO = convertToSignalVO(latestSignal);

        // 获取当前车辆的最大最小电压电流
        String maxVoltageKey = "car:" + carFrameNumber + ":max_voltage";
        String minVoltageKey = "car:" + carFrameNumber + ":min_voltage";
        String maxCurrentKey = "car:" + carFrameNumber + ":max_current";
        String minCurrentKey = "car:" + carFrameNumber + ":min_current";

        Double maxVoltage = (Double) redisTemplate.opsForValue().get(maxVoltageKey);
        Double minVoltage = (Double) redisTemplate.opsForValue().get(minVoltageKey);
        Double maxCurrent = (Double) redisTemplate.opsForValue().get(maxCurrentKey);
        Double minCurrent = (Double) redisTemplate.opsForValue().get(minCurrentKey);

        signalVO.setVoltageMax(maxVoltage);
        signalVO.setVoltageMin(minVoltage);
        signalVO.setCurrentMax(maxCurrent);
        signalVO.setCurrentMin(minCurrent);

        // 将查询结果存入Redis缓存
        String signalCacheKey = SIGNAL_CACHE_PREFIX + carFrameNumber;
        redisTemplate.opsForValue().set(signalCacheKey, signalVO, SIGNAL_CACHE_EXPIRE_TIME, TimeUnit.SECONDS);

        return signalVO;
    }

    // 其他已有方法...

    /**
     * 获取所有车架编号
     * @return
     */
    public List<Integer> getAllFrameNumbers() {
        return signalMapper.selectAllFrameNumbers();
    }

    /**
     * 根据车架编号获取最新信号
     * @param frameNumber
     * @return
     */
    public Signal getLatestSignalByFrameNumber(Integer frameNumber) {
        return signalMapper.selectLatestByFrameNumber(frameNumber);
    }

    /**
     * 解析excel文件，填入信息数据
     * @param inputStream
     */
    @Transactional
    @Override
    public void processExcel(InputStream inputStream) throws IOException {
        List<Signal> signals = new ArrayList<>();

        try(XSSFWorkbook workbook = new XSSFWorkbook(inputStream)) {
            //获取第一个工作表
            XSSFSheet sheet = workbook.getSheetAt(0);

            //遍历工作表中的每一行（跳过标题行）
            for (Row row : sheet) {
                if (row.getRowNum() == 0) {
                    continue;
                }
                //判断是否为空行
                if (isRowEmpty(row)) continue;

                //解析单元格
                Signal signal = new Signal();
                signal.setVehicleFrameNumber((long) row.getCell(0).getNumericCellValue());
                signal.setVoltage(row.getCell(1).getNumericCellValue());
                signal.setCurrent(row.getCell(2).getNumericCellValue());
                signal.setStatus(0);
                signal.setSignalTime(LocalDateTime.now());
                signals.add(signal);

            }
        }
        //数据校验（检查空数据）
        if (signals.isEmpty()){
            throw new BusinessException(0,"Excel文件中没有数据");
        }

        for (Signal signal : signals) {
            if (signal.getVehicleFrameNumber() == null || signal.getVoltage() == null || signal.getCurrent() == null) {
                //除去这条信息
                signals.remove(signal);
            }
        }
        //批量插入数据
        for (Signal signal : signals) {
            signalMapper.insert(signal);
        }
    }

    // 辅助方法：判断行是否为空
    private boolean isRowEmpty(Row row) {
        if (row == null) return true;
        for (int c = row.getFirstCellNum(); c < row.getLastCellNum(); c++) {
            Cell cell = row.getCell(c, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
            if (cell.getCellTypeEnum() != CellType.BLANK) {
                return false;
            }
        }
        return true;
    }
}
